package org.hagen.mmia.yars.collection;

import java.io.IOException;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.BytesRef;
import org.hagen.mmia.yars.client.User;
import org.hagen.mmia.yars.engine.Index;

import org.hagen.mmia.yars.agent.utils.IntegerTreeMap;

/*
 * document representation
 */
public class Document {

	// core elements
	private String					  title	  = null;
	private String					  content = null;
	public  long					  length  = -1;
	
	// singletons
	private SortedMap<String, Double> MapIDF  = null;
	private SortedMap<String, Double> MapTF	  = null;
	
	public double				scoreBuffer[] = null;
	public static final int		SCORE_INITIAL = -1;

	public  String	 			ID;
	public  int		 			index;
	
	/*
	 * constructor
	 */
	public Document( int index, String ID ) {
		this.index = index;
		this.ID    = ID;
		
		initScores();
	}

	/*
	 * getter / setter
	 */
	public String getTitle() {
		
		if( this.title == null ) {
			try {
				this.title = Index.getReader().document(this.index).get( Index.FIELD_TITLE );
			} catch (IOException e) {
				this.title = null;
			}
		}

		return title;
	}
	
	public String getContent() {
		
		if( this.content == null ) {
			try {
				this.content = Index.getReader().document(this.index).get( Index.FIELD_CONTENT );
			} catch (IOException e) {
				this.content = null;
			}
		}

		return content;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public void setContent(String content) {
		this.content = content;
	}
	
	public double getScore( int userID ) {
		
		return scoreBuffer[userID];
	}

	public void setScore( int userID, double score ) {
		
		scoreBuffer[userID] = score;
	}
	
	public void initScores() {
		
		scoreBuffer = new double[User.MAX_NO_OF_USERS];		
		for( int i=0; i<User.MAX_NO_OF_USERS; i++ ) {
			scoreBuffer[i] = SCORE_INITIAL;	
		}
	}
	
	public long getDocumentLength() {
		
		if( length < 0 ) {
		
			try {
				Terms vector = Index.getReader().getTermVector(this.index, Index.FIELD_CONTENT);
	
				// OHSUMED contains some empty documents that we skip
				if( vector == null ) {
					length = 0;
					return length;
				}
				
				TermsEnum termsEnum = vector.iterator(null);
				
				while (termsEnum.next() != null) {
					length += termsEnum.totalTermFreq();
				}
			
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		return length;
	}
	
	/*
	 * list of terms sorted by term frequency
	 */
	public SortedMap<String, Double> getFrequencies( ) {
		
		if( MapTF == null ) {
		
			MapTF = new TreeMap<String, Double>();
			
			try {
				Terms vector = Index.getReader().getTermVector(this.index, Index.FIELD_CONTENT);
				if( vector == null )
					return null;
	
				TermsEnum termsEnum = vector.iterator(null);
				
				BytesRef text = null;
				while ((text = termsEnum.next()) != null) {
					String term = text.utf8ToString();

					double tf = (double) termsEnum.totalTermFreq();
					
			        MapTF.put( term, tf );
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
		return MapTF; 
	}	
	
	/*
	 * list of terms sorted by term frequency
	 */
	public SortedMap<String, Double> getFrequencies( IntegerTreeMap df ) {
		
		if( MapIDF == null ) {
		
			MapIDF = new TreeMap<String, Double>();
			
			try {
				Terms vector = Index.getReader().getTermVector(this.index, Index.FIELD_CONTENT);
				if( vector == null )
					return null;
	
				TermsEnum termsEnum = vector.iterator(null);
				
				BytesRef text = null;
				while ((text = termsEnum.next()) != null) {
					String term = text.utf8ToString();

					double tf = (double) termsEnum.totalTermFreq();
	
					// document frequency for term
					double documentFrequency = ( double )df.get( term );
					
					double idf = Math.log10( df.size() / documentFrequency );
					
					MapIDF.put( term, tf * idf );
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
		return MapIDF; 
	}
	
	/*
	 * print
	 */
	public void print( ) {
		String t = this.getTitle();
		String c = this.getContent();
		
		System.out.println( "document <" + ID + "> " + t );
		System.out.println( "\t " + c );
		
	}
}
